﻿using System.Collections.Generic;
using Microsoft.Extensions.Localization;
using Volo.Abp.Caching;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Localization;

namespace YunxSoft.Abp.LanguageManagement;

public class DynamicResourceLocalizer : IDynamicResourceLocalizer, ISingletonDependency
{
    protected ILanguageTextRepository LanguageTextRepository { get; }

    protected IDistributedCache<LanguageTextCacheItem> Cache { get; }

    public DynamicResourceLocalizer(ILanguageTextRepository languageTextRepository, IDistributedCache<LanguageTextCacheItem> cache)
    {
        this.LanguageTextRepository = languageTextRepository;
        this.Cache = cache;
    }

    public virtual LocalizedString GetOrNull(LocalizationResource resource, string cultureName, string name)
    {
        string orDefault = this.GetCacheItem(resource, cultureName).Dictionary.GetOrDefault<string, string>(name);
        if (orDefault == null)
        {
            return null;
        }
        return new LocalizedString(name, orDefault);
    }

    public virtual void Fill(LocalizationResource resource, string cultureName, Dictionary<string, LocalizedString> dictionary)
    {
        foreach (KeyValuePair<string, string> keyValuePair in this.GetCacheItem(resource, cultureName).Dictionary)
        {
            dictionary[keyValuePair.Key] = new LocalizedString(keyValuePair.Key, keyValuePair.Value);
        }
    }

    protected virtual LanguageTextCacheItem GetCacheItem(LocalizationResource resource, string cultureName)
    {
        var cacheItem = new CacheItem();
        cacheItem.localizer = this;
        cacheItem.resource = resource;
        cacheItem.key = cultureName;
        return this.Cache.GetOrAdd(LanguageTextCacheItem.CalculateCacheKey(cacheItem.resource.ResourceName, cacheItem.key), cacheItem.Create);
    }

    protected virtual LanguageTextCacheItem CreateCacheItem(LocalizationResource resource, string cultureName)
    {
        LanguageTextCacheItem languageTextCacheItem = new LanguageTextCacheItem();
        foreach (LanguageText languageText in this.LanguageTextRepository.GetList(resource.ResourceName, cultureName))
        {
            languageTextCacheItem.Dictionary[languageText.Name] = languageText.Value;
        }
        return languageTextCacheItem;
    }

    private sealed class CacheItem
    {

        internal LanguageTextCacheItem Create()
        {
            return this.localizer.CreateCacheItem(this.resource, this.key);
        }

        public DynamicResourceLocalizer localizer;

        public LocalizationResource resource;

        public string key;
    }
}